package com.bjy.qa.agent.tools.juel;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 参数
 */
public class Param {
    private static final Logger logger = LoggerFactory.getLogger(Param.class);

    private static final Map<String, Long> TIME_MAP = new HashMap();
    private static final Pattern dateParamPattern = Pattern.compile("(\\s*[+-]?[0-9]+\\s*),(\\s*[^\\),]*\\s*),?(\\s*[YyMDdHhmSs]?\\s*)");
    private static Random random = new Random();

    static {
        TIME_MAP.put("ms", Long.valueOf(1L));
        TIME_MAP.put("s", Long.valueOf(TimeUnit.SECONDS.toMillis(1L)));
        TIME_MAP.put("m", Long.valueOf(TimeUnit.MINUTES.toMillis(1L)));
        TIME_MAP.put("h", Long.valueOf(TimeUnit.HOURS.toMillis(1L)));
        TIME_MAP.put("d", Long.valueOf(TimeUnit.DAYS.toMillis(1L)));
    }

    /**
     * 转义（ 将 \r\n 转义成 \\\\r\\\\n，\n 转义成 \\\\n ）
     * @param str 字符串
     * @return
     */
    public static String escape(String str) {
        return str.replaceAll("\r\n", "\\\\r\\\\n").replace("\n", "\\n");
    }

    /**
     * 反转义
     * @param str 字符串
     * @return
     */
    public static String unescape(String str) {
        return str.replaceAll("\\\\r\\\\n", "\r\n").replaceAll("\\\\n", "\n");
    }

    /**
     * 时间戳（formatExpression=ms 为 13 位时间戳，formatExpression=s 为 10 位时间戳，formatExpression=m 为 8 位时间戳 依次类推）
     * @param formatExpression ms、s、m、h、d
     * @return
     */
    public static String timestamp(String formatExpression) {
        Date date = new Date();
        Long integer = (Long) TIME_MAP.get(formatExpression.toLowerCase());
        if (integer != null) {
            return String.valueOf(date.getTime() / integer.longValue());
        }
        return String.valueOf(date.getTime());
    }

    /**
     * 日期时间
     * @param param 参数（diff,formatExpression,diff: 参数第一部分是+或-一定时间，中间参数是格式化表达式，最后一个参数是+或-的类型）
     * @return
     */
    public static String date(String param) {
        String diff = "0"; // +或-一定时间
        String formatExpression = ""; // 格式化表达式
        String diffType = ""; // +或-的类型，y：年、M：月，d：日，h：时、m：分、s：秒

        // 利用正则表达式，从参数中匹出三个参数
        Matcher matcher = dateParamPattern.matcher(param);
        while (matcher.find()) {
            String group1 = matcher.group(1);
            diff = StringUtils.trim(group1);
            if ((StringUtils.isNotBlank(diff)) && (diff.startsWith("+"))) {
                diff = diff.substring(1);
            }

            String group2 = matcher.group(2);
            formatExpression = StringUtils.trim(group2);

            diffType = matcher.group(3);
        }

        Date date = getDiffDate(diffType, Integer.valueOf(diff));

        try {
            String formatDate = formatDateString(param, formatExpression, date);
            return formatDate;
        } catch (Exception e) {
            return e.getMessage();
        }
    }

    /**
     * 得到 +或- 的日期
     * @param diffType +或-的类型，y：年、M：月，d：日，h：时、m：分、s：秒
     * @param diff +或-一定时间
     * @return
     */
    private static Date getDiffDate(String diffType, Integer diff) {
        diffType = StringUtils.trim(diffType);
        if (StringUtils.isBlank(diffType)) {
            return DateUtils.addDays(new Date(), diff.intValue());
        }
        switch (diffType.charAt(0)) {
            case 'Y':
            case 'y':
                return DateUtils.addYears(new Date(), diff.intValue());
            case 'M':
                return DateUtils.addMonths(new Date(), diff.intValue());
            case 'D':
            case 'd':
                return DateUtils.addDays(new Date(), diff.intValue());
            case 'H':
            case 'h':
                return DateUtils.addHours(new Date(), diff.intValue());
            case 'm':
                return DateUtils.addMinutes(new Date(), diff.intValue());
            case 'S':
            case 's':
                return DateUtils.addSeconds(new Date(), diff.intValue());
        }
        return DateUtils.addDays(new Date(), diff.intValue());
    }

    /**
     * 将日期格式化成字符串
     * @param param 参数
     * @param formatExpression 格式化表达式
     * @param date date
     * @return
     */
    private static String formatDateString(String param, String formatExpression, Date date) {
        if (formatExpression.equalsIgnoreCase("milliSeconds")) { // 预期格式写成 milliSeconds 直接返回时间毫秒值
            return String.valueOf(date.getTime());
        } else if (formatExpression.equalsIgnoreCase("seconds")) { // 预期格式写成 seconds 直接返回时间毫秒值
                return String.valueOf(date.getTime() / 1000);
        } else { // 其它格式再格式化返回
            if (StringUtils.isBlank(formatExpression))
                throw new RuntimeException("在参数：" + param + " 中提取出的时间格式化表达式非法: " + formatExpression);

            try {
                DateFormat dateFormat = new SimpleDateFormat(formatExpression);
                return dateFormat.format(date);
            } catch (Exception e) {
            }
            throw new RuntimeException("在参数：" + param + " 中提取出的时间格式化表达式非法: " + formatExpression);
        }
    }

    /**
     * 字符串
     * @param length 指定长度
     * @return
     */
    public static String string(int length) {
        if (length <= 0) return "";
        StringBuilder sb = new StringBuilder(length);
        for (int i = 0; i < length; i++) {
            sb.append(getRandomStr());
        }
        return sb.toString();
    }

    /**
     * 随机产生一个字符
     * @return
     */
    private static char getRandomStr() {
        int index = random.nextInt(JuelHelper.juelConf.getStrChar().length());
        return JuelHelper.juelConf.getStrChar().charAt(index);
    }

    /**
     * 特殊字符串
     * @param length 指定长度
     * @return
     */
    public static String specialString(int length) {
        if (length <= 0) return "";
        StringBuilder sb = new StringBuilder(length);
        for (int i = 0; i < length; i++) {
            sb.append(getSpecialRandomStr());
        }
        return sb.toString();
    }

    /**
     * 随机产生一个特殊字符
     * @return
     */
    private static char getSpecialRandomStr() {
        int index = random.nextInt(JuelHelper.juelConf.getSpecialChar().length());
        return JuelHelper.juelConf.getSpecialChar().charAt(index);
    }

    /**
     * 随机数
     * @param length 指定长度
     * @return
     */
    public static String random(int length) {
        if (length <= 0) return "";
        StringBuilder sb = new StringBuilder(length);
        for (int i = 0; i < length; i++) {
            sb.append(getRandom());
        }
        return sb.toString();
    }

    /**
     * 随机产生一个0-9的随机数
     * @return
     */
    private static int getRandom() {
        return random.nextInt(9);
    }
}
